"""
异常市场检测器
检测涨跌停板、成交量异常、集合竞价等特殊市场状态
"""
import logging
import pandas as pd
from typing import Dict
from datetime import datetime

logger = logging.getLogger('AbnormalMarketDetector')


class AbnormalMarketDetector:
    """
    异常市场检测器
    检测各种异常市场条件并提供相应的处理建议
    """
    
    @staticmethod
    def detect_abnormal_conditions(stock_data: pd.DataFrame, 
                                   current_index: int) -> Dict[str, any]:
        """
        检测异常市场条件
        
        Args:
            stock_data: 股票数据
            current_index: 当前索引
            
        Returns:
            Dict: 异常条件字典，key为异常类型，value为异常详情
        """
        abnormalities = {}
        
        try:
            current_data = stock_data.iloc[current_index]
            
            # 检测1: 涨跌停板
            if current_index > 0:
                prev_data = stock_data.iloc[current_index-1]
                limit_status = AbnormalMarketDetector._detect_limit_move(
                    current_data, prev_data
                )
                if limit_status:
                    abnormalities['limit'] = limit_status
            
            # 检测2: 成交量异常
            volume_abnormal = AbnormalMarketDetector._detect_volume_abnormal(
                stock_data, current_index
            )
            if volume_abnormal:
                abnormalities.update(volume_abnormal)
            
            # 检测3: 集合竞价时段
            if 'time' in current_data or 'datetime' in current_data:
                current_time = current_data.get('time') or current_data.get('datetime')
                if isinstance(current_time, (datetime, pd.Timestamp)):
                    if AbnormalMarketDetector._is_call_auction(current_time):
                        abnormalities['call_auction'] = True
            
            # 检测4: 价格剧烈波动
            price_volatility = AbnormalMarketDetector._detect_price_volatility(
                stock_data, current_index
            )
            if price_volatility:
                abnormalities['price_volatility'] = price_volatility
                
        except Exception as e:
            logger.warning(f"异常市场检测失败: {e}")
        
        return abnormalities
    
    @staticmethod
    def _detect_limit_move(current_data: pd.Series, prev_data: pd.Series) -> str:
        """
        检测涨跌停板
        
        Returns:
            str: 'up' (涨停) | 'down' (跌停) | None
        """
        try:
            prev_close = prev_data['close']
            current_close = current_data['close']
            
            if prev_close == 0:
                return None
            
            change_pct = (current_close - prev_close) / prev_close
            
            # 接近10%涨跌停（考虑ST股票5%涨跌停）
            if change_pct >= 0.095:
                return 'up'
            elif change_pct <= -0.095:
                return 'down'
            elif abs(change_pct) >= 0.045:  # ST股票
                if change_pct > 0:
                    return 'up_st'
                else:
                    return 'down_st'
            
            return None
            
        except Exception:
            return None
    
    @staticmethod
    def _detect_volume_abnormal(stock_data: pd.DataFrame, 
                               current_index: int) -> Dict[str, bool]:
        """
        检测成交量异常
        
        Returns:
            Dict: {'volume_surge': True} 或 {'volume_dry': True} 或 {}
        """
        abnormal = {}
        
        try:
            if current_index < 5:
                return abnormal
            
            current_volume = stock_data.iloc[current_index]['volume']
            recent_avg_volume = stock_data.iloc[
                current_index-5:current_index
            ]['volume'].mean()
            
            if recent_avg_volume == 0:
                return abnormal
            
            # 成交量异常放大（超过5倍）
            if current_volume > recent_avg_volume * 5:
                abnormal['volume_surge'] = True
            
            # 成交量异常萎缩（低于20%）
            elif current_volume < recent_avg_volume * 0.2:
                abnormal['volume_dry'] = True
                
        except Exception:
            pass
        
        return abnormal
    
    @staticmethod
    def _is_call_auction(current_time: datetime) -> bool:
        """
        检测是否在集合竞价时段
        
        Returns:
            bool: 是否在集合竞价时段
        """
        try:
            hour = current_time.hour
            minute = current_time.minute
            
            # 开盘集合竞价: 9:15-9:25
            if (hour == 9 and 15 <= minute <= 25):
                return True
            
            # 尾盘集合竞价: 14:57-15:00
            if (hour == 14 and minute >= 57) or (hour == 15 and minute == 0):
                return True
            
            return False
            
        except Exception:
            return False
    
    @staticmethod
    def _detect_price_volatility(stock_data: pd.DataFrame, 
                                current_index: int) -> float:
        """
        检测价格剧烈波动
        
        Returns:
            float: 波动率（如果大于0.05则认为剧烈波动）
        """
        try:
            if current_index < 5:
                return 0.0
            
            recent_prices = stock_data.iloc[
                current_index-5:current_index+1
            ]['close']
            
            # 计算价格波动率（标准差/均值）
            mean_price = recent_prices.mean()
            if mean_price == 0:
                return 0.0
            
            volatility = recent_prices.std() / mean_price
            
            return volatility if volatility > 0.05 else 0.0
            
        except Exception:
            return 0.0

